/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.geoviewer;

import com.vividsolutions.jts.geom.Geometry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Action;
import nl.cloudfarming.client.model.Bean;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;

/**
 * A layer object represents an item in a layer.
 * The geometry of the object is used to determine the 
 * location where it should be drawn
 *
 * @author Timon Veenstra
 */
public interface LayerObject<G extends Geometry, B extends Bean> {

    /**
     * data object representing this layer object
     * 
     * @return
     */
    B getObject();

    /**
     * describes the geometry of the object
     * this can be a point, or a multipolygon
     *
     * @return
     */
    G getGeometry();

    /**
     *
     * @return
     */
    String getKey();

    /**
     *
     * @return
     */
    Object getKeyAttributeValue();

    /**
     * 
     * @return
     */
    String getTooltipText();

    /**
     * get the id of the wrapped object
     *
     * @return
     */
    Long getId();

    /**
     * Save the LayerObject
     */
    void save();

    /**
     * Get actions defined for this specific layer object
     *
     * @return
     */
    LayerObjectAction[] getActions();

    public class Actions {
        private static final Logger LOG = Logger.getLogger("LayerObject.Actions");

        private Actions(){}
        
        /**
         * Merge the layerobject specific actions with the global layerobject actions
         *
         * @param layerObject
         * @return
         */
        public static Action[] mergeActions(LayerObject layerObject) {
            return mergeActions(layerObject, (Action[]) null);
        }

        /**
         * Merge the layerobject specific actions with the global layerobject actions
         *
         * @param layerObject
         * @return
         */
        public static Action[] mergeActions(LayerObject layerObject, Action... actions) {
            // first add all global layer actions from the lookup
            List<Action> globalActions = new ArrayList<Action>();
            for (GenericLayerObjectAction actionDef: Lookup.getDefault().lookupAll(GenericLayerObjectAction.class)){
                try {
                    globalActions.add(actionDef.getClass().newInstance());
                } catch (InstantiationException ex) {
                    LOG.log(Level.FINE, "Instantiation of new {0} failed",actionDef.getClass());
                } catch (IllegalAccessException ex) {
                    LOG.log(Level.FINE, "Instantiation of new {0} failed",actionDef.getClass());
                }
            }

            //
            // add layer specific actions
            //
            LayerObjectAction[] specificActions = layerObject.getActions();
            if (specificActions != null && specificActions.length > 0) {
                globalActions.addAll(Arrays.asList(specificActions));
            }

            if (actions != null && actions.length > 0) {
                globalActions.addAll(Arrays.asList(actions));
            }
            return globalActions.toArray(new Action[]{});
        }
    }
}
